package com.example.demo.pool;

import com.example.demo.util.MysqlUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 参考图1550127887.png
 *
 * @author maxf
 * @version 1.0
 * @ClassName MysqlPoolImpl
 * @Description
 * @date 2019/2/14 15:03
 */
public class MysqlPoolImpl implements MysqlPool {

    //不能使用List<?>,要使用线程安全的

    /**
     * 空闲的连接池
     */
    private LinkedBlockingDeque<Connection> idle;

    /**
     * 使用的连接池
     */
    private LinkedBlockingDeque<Connection> busy;

    /**
     * 最大连接数
     */
    private int maxSize = 10;

    /**
     * 当前连接数
     * <p>要线程安全 不能使用int</p>
     */
    private AtomicInteger activeSize = new AtomicInteger(0);

    /**
     * 初始化
     */
    @Override
    public void init() {
        idle = new LinkedBlockingDeque<>();
        busy = new LinkedBlockingDeque<>();
    }

    /**
     * 销毁
     */
    @Override
    public void destroy() {
        if (busy.size() > 0) {
            Iterator<Connection> iterator = busy.iterator();
            while (iterator.hasNext()) {
                busy.remove(iterator.next());
            }

        }
        if (idle.size() > 0) {
            Iterator<Connection> iterator = idle.iterator();
            while (iterator.hasNext()) {
                idle.remove(iterator.next());
            }

        }
    }

    /**
     * 获取连接
     *
     * @return
     */
    @Override
    public Connection getCoon() {
        //idle有空闲的对象
        Connection coon = idle.poll();
        if (null != coon) {
            busy.offer(coon);
            return coon;
        }

        //idle沒有空闲对象
        // activeSize 小于10：新创建连接，返回
        /**
         * 不使用这种锁
         */
//        synchronized (MysqlPoolImpl.class) {
//            if (activeSize.get() < maxSize) {
//                coon = MysqlUtils.createCoon();
//                busy.offer(coon);
//                activeSize.incrementAndGet();
//                return coon;
//            }
//        }
        /**
         * 使用原子双重判读
         */
        if (activeSize.get() < maxSize) {
            if (activeSize.incrementAndGet() <= maxSize) {//activeSize原子操作，排队进行
                coon = MysqlUtils.createCoon();//创建新连接
                busy.offer(coon);
                return coon;
            }
        }

        // activeSize =10：等待
        try {
            long l = System.currentTimeMillis();
            System.out.println("排队等待" + l);
            //等待10s(连接释放就直接弹出),超时返回null
            coon = idle.poll(10000, TimeUnit.SECONDS);

            //超时
            if (null == coon) {
                System.out.println("等待超时" + l);
                throw new RuntimeException("等待超时 Timeout 10s");
            }
            System.out.println("等到连接" + l);
            busy.offer(coon);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return coon;
    }

    /**
     * 释放连接
     *
     * @param connection
     */
    @Override
    public void release(Connection connection) {
        busy.remove(connection);
        idle.offer(connection);
    }

    /**
     * 连接健康检查
     */
    public void check() {
        for (int i = 0; i < activeSize.get(); i++) {
            Connection connection = idle.poll();
            if (null == connection) {
                return;
            }
            try {
                boolean valid = connection.isValid(2000);
                if (!valid) {
                    System.out.println("连接异常，重建连接");
                    connection = MysqlUtils.createCoon();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            idle.offer(connection);
        }
    }
}
